/*
 * Created on Nov 27, 2005
 */
package dbsucxentW.pathProcessorW;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.LinkedList;

import javax.swing.JOptionPane;

/**
 * @author Seah Boon Siew
 */
// keeps track of steps already processed
public class CurrentPath {
	// klarinda 20061109 add private
	private String _currentPath = "";

	private String _prevCurrentPath = "";

	private String _currentPathStep = ""; // to record the XPath step;

	private LinkedList _currentPathStepList = new LinkedList();

	private LinkedList _currentPathList = new LinkedList();

	// klarinda 20061109

	private int _count = 1; // what's the use of _count?

	private Connection _dbConnection;

	public CurrentPath(Connection conn) {
		_dbConnection = conn;
	};

	// add step without adding name
	public void addStep() {
		_count++;
	}

	public void addString(String string) {
		_currentPathStep += string; // klarinda 20061109
		_currentPath += string;
	}

	public void add(String step) {
		if (step.compareTo("") != 0) {

			/*
			 * klarinda 20060810 wild card and node() should be handled
			 * differently - can't use % if uses %, if there is wild card/node()
			 * in any arbitrary step of XPath, ex: /a/b/ * /c/ in function
			 * getPath(), will behave similar to descendant axis
			 */
			_currentPathStep += "." + step; // klarinda 20061109
			// klarinda 20060810 - add node(): if (step.compareTo("*") == 0){
			if (step.compareTo("*") == 0 || step.compareTo("node()") == 0) {
				step = "%";
				_count++;// klarinda 20060810
			} else {
				_count++;
			}

			_currentPath += "." + step + "#"; // modified by LTM
			System.out
					.println("CurrentPath.add(" + step + "), " + _currentPath); // klarinda
			// 20060808

		}
	}

	public void addForDescendantAxis(String step) {
		if (step.compareTo("") != 0) {
			_currentPathStep += ".." + step; // klarinda 20061109
			if (step.compareTo("*") == 0 || step.compareTo("node()") == 0) {
				step = "%";
				_count++;
				_currentPath += ".%#";
			} else {
				_count++;
				_currentPath += "%." + step + "#";
			}

			// modified by LTM
			System.out
					.println("CurrentPath.add(" + step + "), " + _currentPath); // klarinda

		}
	}

	// added by LTM
	public void removeLast() {
		String[] parts = _currentPath.split("\\.");
		_currentPath = new String();
		for (int i = 1; i < parts.length - 1; i++) {
			_currentPath += ".";
			_currentPath += parts[i];
		}
		_count--;
		// klarinda 20061109
		parts = _currentPathStep.split("\\.");
		_currentPathStep = new String();
		for (int i = 1; i < parts.length - 1; i++) {
			_currentPathStep += ".";
			_currentPathStep += parts[i];
		}
		System.out.println("CurrentPath.removeLast(), _currentPath="
				+ _currentPath);
		// end of klarinda 20061109
	}

	// klarinda 20061108
	public String getLastStep() {
		String[] parts = _currentPathStep.split("\\.");
		return parts[parts.length - 1];
	}

	public String getPathString() {
		return _currentPath;
	}

	// convert path expression into a sequence of path ids
	// public String getPath(){
	public String getPath(boolean isAttr) { // klarinda 20060913 separate
		// Attribute table
		String sqlquery;
		try {
			Statement statement = _dbConnection.createStatement();
			// modified by LTM - /catalog/book && /catalog/boo are the same
			// previously
			// k 20060913 ResultSet results = statement.executeQuery ("SELECT
			// pathid FROM PATH WHERE PATHEXP LIKE '" + _currentPath + "%'");
			// ResultSet results = statement.executeQuery ("SELECT pathid FROM
			// PATH WHERE PATHEXP LIKE '" + _currentPath + ".%'" +
			// " OR PATHEXP like '" + _currentPath + "'");
			// klarinda 20060913 separate Attribute table
			if (isAttr) // only return attribute path
				sqlquery = "SELECT pathid, PathExp FROM PATH WHERE PATHEXP LIKE '"
						+ _currentPath + "%' AND PATHEXP LIKE '%@%'";
			else
				// only return element path
				sqlquery = "SELECT pathid, PathExp FROM PATH WHERE PATHEXP LIKE '"
						+ _currentPath + "%' AND PATHEXP NOT LIKE '%@%'";
			System.out.println("CurrentPath.getPath(" + isAttr + "), "
					+ sqlquery);
			ResultSet results = statement.executeQuery(sqlquery);
			// end of klarinda 20060913

			String res = "(";
			boolean first = true;
			String tempValidXPath = _currentPathStep;
			if (_currentPathStepList.size() == 0) {
				_currentPathStepList.add(_currentPathStep);
			}
			while (results.next()) {
				for (int i = 0; i < _currentPathStepList.size(); i++) {
					_currentPathStep = (String) _currentPathStepList.get(i);
					if (isXPathValid(_currentPathStep.replace(".", "/"),
							results.getString("PathExp"))) {
						if (first) {

							res += results.getString("Pathid");
							first = false;
						} else {
							res += "," + results.getString("Pathid");
						}
					}
				}
			}
			_currentPathStep = tempValidXPath;
			_currentPathStepList = new LinkedList();
			res += ")";

			results.close();
			statement.close();

			if (res.equals("()") && isAttr) // klarinda 20060913
				res = "(0)"; // klarinda 20060913

			return res;

		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
			return "ERROR";
		}
	}

	public String getPrevPath(boolean isAttr) { // erwin 2007-09-06 : needed for
		// processing last position
		// Attribute table
		String sqlquery;
		String _prevCurrentPathStep = _prevCurrentPath.replace(".", "/")
				.replace("#", "").replace("%", "*");
		try {
			Statement statement = _dbConnection.createStatement();
			if (isAttr) // only return attribute path
				sqlquery = "SELECT pathid,PathExp FROM PATH WHERE PATHEXP LIKE '"
						+ _prevCurrentPath + "%' AND PATHEXP LIKE '%@%'";
			else
				// only return element path
				sqlquery = "SELECT pathid,PathExp FROM PATH WHERE PATHEXP LIKE '"
						+ _prevCurrentPath + "%' AND PATHEXP NOT LIKE '%@%'";
			System.out.println("CurrentPath.getPrevPath(" + isAttr + "), "
					+ sqlquery);
			ResultSet results = statement.executeQuery(sqlquery);

			String res = "(";
			boolean first = true;

			while (results.next()) {
				if (isXPathValid(_prevCurrentPathStep.replace(".", "/"),
						results.getString("PathExp"))) {
					if (first) {
						res += results.getString("Pathid");
						first = false;
					} else {
						res += "," + results.getString("Pathid");
					}
				}
			}

			res += ")";

			results.close();
			statement.close();

			if (res.equals("()") && isAttr)
				res = "(0)";

			return res;

		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
			return "ERROR";
		}
	}

	public String getOnePath() {

		try {
			Statement statement = _dbConnection.createStatement();
			ResultSet results = statement
					.executeQuery("SELECT pathid FROM PATH WHERE PATHEXP LIKE '"
							+ _currentPath + " '");
			String res = "(";
			boolean first = true;

			while (results.next()) {
				if (first) {
					res += results.getString("Pathid");
					first = false;
				} else {
					res += "," + results.getString("Pathid");
				}
			}

			res += ")";

			results.close();
			statement.close();

			return res;

		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
			return "ERROR";
		}

	}

	// added by Klarinda 20060808
	// public String getPathExcludeAttr(){
	public String getPathExcludeAttr(boolean isAttr) { // klarinda 20060913
		// separate Attribute
		// table
		String sqlquery;
		try {
			String lastStep = getLastStep(); // 20061109
			removeLast(); // 20061109

			Statement statement = _dbConnection.createStatement();
			// klarinda 20060913
			// sqlquery = "SELECT pathid FROM PATH WHERE PATHEXP LIKE '" +
			// _currentPath + "%' AND PATHEXP NOT LIKE '"+_currentPath+".@%'";
			if (isAttr)
				sqlquery = "SELECT pathid FROM PATH WHERE PATHEXP LIKE '"
						+ _currentPath + "%' AND PATHEXP NOT LIKE '"
						+ _currentPath + ".@%' AND PATHEXP LIKE '%@%'";
			else
				sqlquery = "SELECT pathid FROM PATH WHERE PATHEXP LIKE '"
						+ _currentPath + "%' AND PATHEXP NOT LIKE '%@%'";
			// end of klarinda 20060913
			System.out.println("CurrentPath.getPathExcludeAttr(" + isAttr
					+ "), " + sqlquery);
			ResultSet results = statement.executeQuery(sqlquery);
			String res = "(";
			boolean first = true;

			while (results.next()) {
				if (first) {
					res += results.getString("Pathid");
					first = false;
				} else {
					res += "," + results.getString("Pathid");
				}
			}
			res += ")";

			results.close();
			statement.close();

			if (res.equals("()") && isAttr) // klarinda 20060913
				res = "(0)"; // klarinda 20060913

			add(lastStep); // 20061109

			return res;

		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
			return "ERROR";
		}
	}

	// added by Klarinda 20060810
	// public String getPathExcludeAttrText(){
	public String getPathExcludeAttrText(boolean isAttr) { // klarinda 20060913
		// separate
		// Attribute table
		String sqlquery;
		try {
			String lastStep = getLastStep(); // 20061109
			removeLast(); // 20061109

			Statement statement = _dbConnection.createStatement();
			// klarinda 20060913
			// sqlquery = "SELECT pathid FROM PATH WHERE PATHEXP LIKE '" +
			// _currentPath + ".%' AND PATHEXP NOT LIKE '"+_currentPath+".@%'";
			if (isAttr)
				sqlquery = "SELECT pathid FROM PATH WHERE PATHEXP LIKE '"
						+ _currentPath + ".%' AND PATHEXP NOT LIKE '"
						+ _currentPath + ".@%' AND PATHEXP LIKE '%@%'";
			else
				sqlquery = "SELECT pathid FROM PATH WHERE PATHEXP LIKE '"
						+ _currentPath + ".%' AND PATHEXP NOT LIKE '%@%'";
			System.out.println("CurrentPath.getPathExcludeAttr(" + isAttr
					+ "), " + sqlquery);
			ResultSet results = statement.executeQuery(sqlquery);
			String res = "(";
			boolean first = true;

			while (results.next()) {
				if (first) {
					res += results.getString("Pathid");
					first = false;
				} else {
					res += "," + results.getString("Pathid");
				}
			}
			res += ")";

			results.close();
			statement.close();

			if (res.equals("()") && isAttr) // klarinda 20060913
				res = "(0)"; // klarinda 20060913

			add(lastStep); // 20061109

			return res;

		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
			return "ERROR";
		}
	}

	// public int getLevel(){
	// return _count;
	// }

	// public int getSeperators(){

	// why don't return _count?
	public int getLevel() {
		int i, count;

		count = 0;
		// count++;
		System.out.println("CP:" + _currentPath);

		for (i = 0; i < _currentPath.length(); i++) {
			if (_currentPath.charAt(i) == '.')
				count++;
		}
		return count;
	}

	// klarinda 20060912
	public void clearPath() {
		_prevCurrentPath = _currentPath;
		_currentPath = "";
		_currentPathStep = ""; // klarinda 20061109
		_currentPathStepList = new LinkedList();
		_currentPathList = new LinkedList();
	}

	// klarinda 20061031
	// 20061109 add setCurrentPath
	public int getQNameLevel_setCurrentPath(String QName) {
		String sqlquery;
		int count = 0;
		String _oldcurpath = _prevCurrentPath;
		try {

			_currentPath = ""; // 20061109
			_currentPathStep = ""; // 20061109
			Statement statement = _dbConnection.createStatement();

			sqlquery = "SELECT pathid, pathexp FROM PATH WHERE PATHEXP LIKE '%."
					+ QName + "#%'";
			System.out.println("CurrentPath.getQNameLevel(" + QName + "), "
					+ sqlquery);
			ResultSet results = statement.executeQuery(sqlquery);

			String pathexp = "";
			String[] onepath;
			QName = "." + QName; // because pathexp is split based on #
			int tempCount = -1;
			while (results.next()) {
				_currentPath = ""; // 20061109
				_currentPathStep = ""; // 20061109
				pathexp = results.getString("PathExp");
				System.out.println("CurrentPath.getQNameLevel(" + QName + "), "
						+ pathexp);
				onepath = pathexp.split("#");
				for (int i = 0; i < onepath.length; i++) {
					System.out.println("CurrentPath.getQNameLevel(" + QName
							+ "), [" + i + "] " + onepath[i]);
					_currentPath += onepath[i] + "#"; // 20061109
					_currentPathStep += onepath[i]; // 20061109
					tempCount++;
					if (onepath[i].compareTo(QName) == 0)
						break;
				}
				if (count == 0) {
					count = tempCount;
				} else if (tempCount < count) {
					count = tempCount;
				}
				_currentPathList.add(_currentPath);
				_currentPathStepList.add(_currentPathStep);
			}

			results.close();
			statement.close();
			_currentPath = _oldcurpath + "%" + QName + "#%";
			System.out.println("CurrentPath.getQNameLevel(" + QName
					+ "), count: " + count + ", currentPath: " + _currentPath);
			return count;

		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
					JOptionPane.ERROR_MESSAGE);
			return -1;
		}

	}

	void setCurrentPathString(String Path) {
		_currentPath = Path;
	} // added by wang geng

	public boolean isXPathValid(String pattern, String xpath) {
		String[] STemp = xpath.split("\\.");
		String[] PTemp = pattern.split("/");
		int i = 0;
		if (STemp.length >= PTemp.length) {
			boolean isOK = true;
			for (int x = 1; x < PTemp.length; x++) {
				if (PTemp[x].length() > 1) {
					if (!PTemp[x].trim().substring(PTemp[x].length() - 1)
							.equals("#")) {
						if (!PTemp[x].trim().equals("*")) {
							PTemp[x] = PTemp[x].trim() + "#";

						}
					}
				}
			}

			for (int x = 1; x < PTemp.length; x++) {

				if ((x >= PTemp.length) || ((x + i) >= STemp.length)) {
					isOK = false;
					break;
				}
				if (PTemp[x].trim().equals("*")) {
					continue;
				} else if (PTemp[x].trim().equals("@*")) {
					continue;
				} else if (PTemp[x].trim().length() == 0) {
					if (STemp[x + i].trim().equals(PTemp[x + 1].trim())) {
						i--;
						x++;
						continue;
					}
					i++;
					if (STemp.length <= (x + i)) {
						isOK = false;
						break;
					}
					x--;
					continue;
				} else if (!STemp[x + i].trim().equals(PTemp[x].trim())) {
					isOK = false;
					break;
				}
			}
			if (isOK) {
				return true;
			}
		}
		return false;
	}

}
